package org.infodavid.common.persistence;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

import javax.persistence.PersistenceException;

import org.infodavid.common.model.criteria.ISearchCriteria;
import org.infodavid.common.persistence.exceptions.IErrorHandler;
import org.infodavid.common.util.IVisitor;
import org.joda.time.DateTime;

/**
 * The Interface IDataService.
 * @param <T> the type of the data
 * @param <K> the type of the key
 */
public interface IDataService<T extends IPersistentData<K>,K extends Serializable> {

  /**
   * Gets the entity class.
   * @return the entity class
   */
  Class<? extends T> getEntityClass();

  /**
   * Gets the immutable fields.
   * @return the immutable fields
   */
  String[] getImmutableFields();

  /**
   * Clone.
   * @param src the src
   * @param deep the deep
   * @param asNew the as new
   * @return the t
   */
  T clone(T src, boolean deep, boolean asNew);

  /**
   * delete the elements using the given parameters.
   * @param session the session
   * @param parameters the parameters
   * @throws PersistenceException the persistence exception
   */
  void delete(PersistenceSession session, List<IQueryParameter> parameters)
      throws PersistenceException;

  /**
   * delete all the elements.
   * @param session the session
   * @throws PersistenceException the persistence exception
   */
  void deleteAll(PersistenceSession session) throws PersistenceException;

  /**
   * count the number of instances using the given parameters.
   * @param session the session
   * @param parameters the parameters
   * @return the long
   * @throws PersistenceException the persistence exception
   */
  long count(PersistenceSession session, List<IQueryParameter> parameters)
      throws PersistenceException;

  /**
   * count the number of instances using the given parameters.
   * @param session the session
   * @return the long
   * @throws PersistenceException the persistence exception
   */
  long count(PersistenceSession session) throws PersistenceException;

  /**
   * count the number of instances using the given parameters.
   * @param session the session
   * @param criteria the criteria
   * @return the long
   * @throws PersistenceException the persistence exception
   */
  long count(PersistenceSession session, ISearchCriteria criteria) throws PersistenceException;

  /**
   * find some instances.
   * @param session the session
   * @param entities the entities
   * @param parameters the parameters
   * @return the long
   * @throws PersistenceException the persistence exception
   */
  <L extends IPersistentData<K>> long find(PersistenceSession session, List<L> entities,
      List<IQueryParameter> parameters) throws PersistenceException;

  /**
   * Process data until there is some data. This method can be used if the set of data is reduced by
   * the task.
   * @param session the session
   * @param processor the processor
   * @param parameters the parameters
   * @param batchSize the batch size
   * @return the long
   * @throws PersistenceException the persistence exception
   */
  <L extends IPersistentData<K>> long iterate(final PersistenceSession session,
      final IVisitor<L,Object> processor, List<IQueryParameter> parameters, final int batchSize)
      throws PersistenceException;

  /**
   * Process data until there is some data. This method can be used if the set of data is reduced by
   * the task.
   * @param session the session
   * @param processor the processor
   * @param batchSize the batch size
   * @return the long
   * @throws PersistenceException the persistence exception
   */
  <L extends IPersistentData<K>> long iterate(final PersistenceSession session,
      final IVisitor<L,Object> processor, final int batchSize) throws PersistenceException;

  /**
   * Process data until there is some data. This method can be used if the set of data is reduced by
   * the task.
   * @param session the session
   * @param processor the processor
   * @param criteria the criteria
   * @param batchSize the batch size
   * @return the long
   * @throws PersistenceException the persistence exception
   */
  <L extends IPersistentData<K>> long iterate(final PersistenceSession session,
      final IVisitor<L,Object> processor, ISearchCriteria criteria, final int batchSize)
      throws PersistenceException;

  /**
   * find some instances using the given parameters.
   * @param session the session
   * @param date1 the date1
   * @param date2 the date2
   * @param entities the entities
   * @param parameters the parameters
   * @return the collection
   * @throws PersistenceException the persistence exception
   */
  <L extends IPersistentData<K>> long findByCreationDate(PersistenceSession session,
      DateTime date1, DateTime date2, List<L> entities, List<IQueryParameter> parameters)
      throws PersistenceException;

  /**
   * find some instances using the given parameters.
   * @param session the session
   * @param date1 the date1
   * @param date2 the date2
   * @param entities the entities
   * @param parameters the parameters
   * @return the collection
   * @throws PersistenceException the persistence exception
   */
  <L extends IPersistentData<K>> long findByModificationDate(PersistenceSession session,
      DateTime date1, DateTime date2, List<L> entities, List<IQueryParameter> parameters)
      throws PersistenceException;

  /**
   * find the instance.
   * @param session the session
   * @param value the key
   * @return the data object
   * @throws PersistenceException the persistence exception
   */
  T findByKey(PersistenceSession session, K value) throws PersistenceException;

  /**
   * find the instance.
   * @param session the session
   * @param value the key
   * @param lockType the lock type
   * @return the data object
   * @throws PersistenceException the persistence exception
   */
  T findByKey(PersistenceSession session, K value, ILockable.ELockType lockType)
      throws PersistenceException;

  /**
   * update an instance.
   * @param session the session
   * @param collection the objects to update
   * @throws PersistenceException the persistence exception
   */
  void update(PersistenceSession session, Collection<T> collection) throws PersistenceException;

  /**
   * update an instance.
   * @param session the session
   * @param value the object to update
   * @throws PersistenceException the persistence exception
   */
  void update(PersistenceSession session, T value) throws PersistenceException;

  /**
   * insert an instance.
   * @param session the session
   * @param collection the objects to insert
   * @throws PersistenceException the persistence exception
   */
  void insert(PersistenceSession session, Collection<T> collection) throws PersistenceException;

  /**
   * insert an instance.
   * @param session the session
   * @param value the object to insert
   * @throws PersistenceException the persistence exception
   */
  void insert(PersistenceSession session, T value) throws PersistenceException;

  /**
   * remove an instance.
   * @param <E> the element type
   * @param session the session
   * @param collection the objects to remove
   * @throws PersistenceException the persistence exception
   */
  <L extends IPersistentData<K>> void delete(PersistenceSession session, Collection<L> collection)
      throws PersistenceException;

  /**
   * remove an instance.
   * @param session the session
   * @param keys the keys of the objects to remove
   * @throws PersistenceException the persistence exception
   */
  void deleteByKeys(PersistenceSession session, Collection<K> keys) throws PersistenceException;

  /**
   * remove an instance.
   * @param <E> the element type
   * @param session the session
   * @param value the object to remove
   * @throws PersistenceException the persistence exception
   */
  <L extends IPersistentData<K>> void delete(PersistenceSession session, L value)
      throws PersistenceException;

  /**
   * remove an instance.
   * @param session the session
   * @param key the key of the object to remove
   * @throws PersistenceException the persistence exception
   */
  void delete(PersistenceSession session, K key) throws PersistenceException;

  /**
   * New instance.
   * @return the new instance
   * @throws InstantiationException the instantiation exception
   */
  T create() throws InstantiationException;

  /**
   * Merge.
   * @param partial the partial
   * @param target the target
   * @throws PersistenceException the persistence exception
   */
  void merge(T partial, T target) throws PersistenceException;

  /**
   * Gets the error handler.
   * @return the errorHandler
   */
  IErrorHandler<PersistenceException> getErrorHandler();

  /**
   * Sets the error handler.
   * @param value the error handler
   */
  void setErrorHandler(final IErrorHandler<PersistenceException> value);
}
